package lol.clann.minecraft.springboot.plugin.bukkit.impl;

import lol.clann.minecraft.springboot.api.bukkit.utils.ItemStackUtils;
import lol.clann.minecraft.springboot.api.bukkit.utils.MenuUtils;
import lol.clann.minecraft.springboot.api.bukkit.utils.NBTUtils;
import lol.clann.minecraft.springboot.api.bukkit.utils.ServerUtils;
import lol.clann.minecraft.springboot.api.model.menu.Menu;
import lol.clann.minecraft.springboot.api.model.menu.MenuInventory;
import lol.clann.minecraft.springboot.api.service.CacheService;
import net.minecraft.server.v1_7_R4.NBTTagCompound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: zyp
 * @date: 2020/11/2 3:48 下午
 */
@Service
public class MenuUtilsImpl implements Listener, MenuUtils {
    @Autowired
    private ItemStackUtils itemStackUtils;
    @Autowired
    private NBTUtils nbtUtils;
    @Autowired
    private ServerUtils serverUtils;
    @Autowired
    private CacheService cacheService;
    private Map<Long, Menu> menuCache = new ConcurrentHashMap<>();

    @Override
    public ItemStackUtils getItemStackUtils() {
        return itemStackUtils;
    }

    @Override
    public NBTUtils getNbtUtils() {
        return nbtUtils;
    }

    @Override
    public ServerUtils getServerUtils() {
        return serverUtils;
    }

    @Override
    public CacheService getCacheService() {
        return cacheService;
    }

    @Override
    public Menu.MenuBuilder createMenu() {
        return new Menu.MenuBuilder(this);
    }

    @Override
    public void registerMenu(Menu menu) {
        if (menuCache.containsKey(menu.getUid())) {
            throw new RuntimeException("重复注册:" + menu.getUid());
        }
        menuCache.put(menu.getUid(), menu);
    }

    @Override
    public void unregisterMenu(Menu menu) {
        menuCache.remove(menu.getUid());
    }

    @Override
    public void setUid(ItemStack itemStack, long uid) {
        NBTTagCompound tag = itemStackUtils.getTag(itemStack);
        if (tag == null) {
            tag = nbtUtils.newNBTTagCompound();
            itemStackUtils.setTag(itemStack, tag);
        }
        nbtUtils.setValue(tag, "icon.uid", uid);
    }

    /**
     * 读取图标的uid,如果没有,就返回-1
     *
     * @param itemStack
     * @return
     */
    @Override
    public long getUid(ItemStack itemStack) {
        NBTTagCompound tag = itemStackUtils.getTag(itemStack);
        if (tag == null) {
            return -1;
        }
        Object uid = nbtUtils.getValue("icon.uid");
        if (!(uid instanceof Long)) {
            return -1;
        }
        return (Long) uid;
    }

    @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
    private void onEvent(InventoryCloseEvent event) throws Throwable {
        Inventory inventory = event.getInventory();
        if (!(inventory instanceof MenuInventory)) {
            return;
        }
        MenuInventory mi = (MenuInventory) inventory;
        Menu menu = menuCache.get(mi.getUid());
        menu.onClose(mi);
    }

    @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
    private void onEvent(InventoryClickEvent event) throws Throwable {
        Inventory inventory = event.getInventory();
        if (!(inventory instanceof MenuInventory)) {
            return;
        }
        event.setCancelled(true);
        ItemStack currentItem = event.getCurrentItem();
        if (itemStackUtils.isEmpty(currentItem)) {
            return;
        }
        MenuInventory mi = (MenuInventory) inventory;
        long menuUid = mi.getMenuUid();
        long iconUid = getUid(currentItem);
        if (iconUid == -1) {
            return;
        }
        Menu menu = menuCache.get(menuUid);
        Player player = (Player) event.getWhoClicked();
        menu.onClick(player, event, iconUid);
    }

    @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
    private void onEvent(InventoryDragEvent event) throws Throwable {
        Inventory inventory = event.getInventory();
        if (!(inventory instanceof MenuInventory)) {
            return;
        }
        event.setCancelled(true);
    }

    @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
    private void onEvent(InventoryMoveItemEvent event) throws Throwable {
        if (!(event.getDestination() instanceof MenuInventory)) {
            event.setCancelled(true);
            return;
        }
        if (!(event.getSource() instanceof MenuInventory)) {
            event.setCancelled(true);
            return;
        }
    }
}
